﻿//SCCM 2012 Application Importer (SCCMAppImporter)
//Copyright (c) 2013 by Mattias Benninge
//
//This program is dual-licensed; you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation; either version 2 of the License, or
//(at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
//Alternatively, you can license this library under a commercial license,
//please contact Mattias Benninge for more information.
//
//Contact Information:
//https://www.codeplex.com/site/users/contact/mattben?OriginalUrl=http://www.codeplex.com/site/users/view/mattben

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.DirectoryServices;
using System.Drawing.Drawing2D;
using System.Drawing;
using System.Linq;
using System.Management;
using System.Text;
using System.Windows.Forms;
using Microsoft.ConfigurationManagement.ManagementProvider;
using Microsoft.ConfigurationManagement.ManagementProvider.WqlQueryEngine;
using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using WI = WindowsInstaller;
using System.Xml;
using System.Xml.Linq;
using MSI = Microsoft.ConfigurationManagement.ApplicationManagement.MsiInstaller;
using AM = Microsoft.ConfigurationManagement.ApplicationManagement;
using Microsoft.ConfigurationManagement.ApplicationManagement.Serialization;
using Microsoft.ConfigurationManagement.DesiredConfigurationManagement;
using Microsoft.ConfigurationManagement.DesiredConfigurationManagement.ExpressionOperators;
using Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Expressions;
using Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Rules;

using System.Threading;

namespace AppImporter
{
    public partial class MainForm : Form
    {
        private Settings SettingsBrowseDialog;
        private AppfolderBrowse AppfolderBrowseDialog;
        private CollectionBrowse CollectionBrowseDialog;
        public object SCCMWQLConnection;
        public string strmsipath;
        public string strmsifilename;
        public string strmstfilename;
        public string strSiteID;
        public string advCollectionID;
        public XmlDocument guiConfig = new XmlDocument();
        
        public MainForm()
        {
            InitializeComponent();

            this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.DoubleBuffer | ControlStyles.UserPaint | ControlStyles.ResizeRedraw, true);
        }

        //Public
        public string XMLSaved;
        public string MSIGuid;

        //Pivate
        private bool ClosePress = false;
        private bool MinPress = false;
        private bool FormDrag = false;
        private bool FileActive = false;
        private bool HelpActive = false;
        private bool FileHot = false;
        private bool HelpHot = false;
        private bool OverClose;
        private bool OverMin;
        
        protected override System.Windows.Forms.CreateParams CreateParams
        {
            get
            {
                CreateParams cp = base.CreateParams;
                const int WS_CLIPCHILDREN = 0x2000000;
                const int WS_MINIMIZEBOX = 0x20000;
                //const int WS_MAXIMIZEBOX = 0x10000;
                const int WS_SYSMENU = 0x80000;

                const int CS_DBLCLKS = 0x8;
                const int CS_DROPSHADOW = 0x20000;

                int ClassFlags = CS_DBLCLKS;
                int OSVER = Environment.OSVersion.Version.Major * 10;
                OSVER += Environment.OSVersion.Version.Minor;
                if (OSVER >= 51) ClassFlags = CS_DBLCLKS | CS_DROPSHADOW;

                cp.Style = WS_CLIPCHILDREN | WS_MINIMIZEBOX | WS_SYSMENU; //| WS_MAXIMIZEBOX
                cp.ClassStyle = ClassFlags;
                
                return cp;
            }
        }
        
        private void MainForm_Load(object sender, System.EventArgs e)
        {
            this.labelFile.Location = new Point(10, 26);
            this.labelHelp.Location = new Point(labelFile.Right, 26);
            this.labelFile.Font = SystemInformation.MenuFont;
            this.labelHelp.Font = SystemInformation.MenuFont;
            this.Region = new Region(OrgShape);

            LoadSettings();
            //bt_browsemsi.Enabled = false;
            try
            {
                //Initialize(guiConfig.SelectSingleNode("/AppImporter/SCCMServer").InnerText.ToString());
                this.SCCMWQLConnection = this.Connect(guiConfig.SelectSingleNode("/AppImporter/SCCMServer").InnerText);

            }
            catch (Exception ex)
            {
                MessageBox.Show("Could not connect to server, wrong credentials or servername?");
                Ballontip("Error", ex.Message, ToolTipIcon.Error, 6000);
                //MessageBox.Show(ex.ToString());
            }
            finally {
                Properties.Settings.Default.FirstRun = "false";
            }

            GetSMSIdentID((WqlConnectionManager)SCCMWQLConnection);


            //Ballontip("test", "text test", ToolTipIcon.Warning, 6000);

           // IResultObject SMSIdent = SCCMWQLConnection.CreateInstance("SMS_Identification");
            //ManagementBaseObject outSiteParams = SMSIdent.InvokeMethod("GetSiteID", null, null);

            //string query = "SELECT * FROM SMS_SystemResourceList WHERE RoleName='SMS Distribution Point' AND SiteCode='" + siteCode + "' AND NALPath LIKE '%" + serverName.Replace(@"\", @"\\") + "'";

            //IResultObject listOfResources = connectionManager.QueryProcessor.ExecuteQuery(query);

            //this.SCCMWQLConnection = this.Connect(guiConfig.SelectSingleNode("/AppImporter/SCCMServer").InnerText);
            //SCCMWQLConnection
            //$identificationClass = [WMICLASS]"\\$($SccmServer.Machine)\$($SccmServer.Namespace):SMS_Identification"
            //$cls = Get-WmiObject SMS_Identification -namespace $SccmServer.Namespace -ComputerName $SccmServer.Machine -list
            //$tmp = $identificationClass.GetSiteID().SiteID
            //return "ScopeId_$($tmp.Substring(1,$tmp.Length -2))"
            //Microsoft.ConfigurationManagement.ApplicationManagement.MsiInstallerTechnology.Add(
        }

        public static void Initialize(string siteServerName)
        {
            Microsoft.ConfigurationManagement.ApplicationManagement.Validator.CheckForNull(siteServerName, "siteServerName");

            //Log("Connecting to the SMS Provider on computer [{0}].", siteServerName);

            // Creates a connection to the SMS Provider.
            WqlConnectionManager connectionManager = new WqlConnectionManager();
            connectionManager.Connect(siteServerName);
            //Log("Initializing the ApplicationFactory.");
            // Initialize application wrapper and factory for creating the SMS Provider application object.
            //factory = new ApplicationFactory();
            //wrapper = AppManWrapper.Create(connectionManager, factory) as AppManWrapper;



        }

        private void LoadSettings()
        {
            //MessageBox.Show(Environment.CurrentDirectory.ToString());
            try
            {
                guiConfig.Load(@".\Settings.xml"); // .Load(@"..\..\Settings.xml");
                tb_prefix.Text = guiConfig.SelectSingleNode("/AppImporter/Prefix").InnerText;
            }
            catch (Exception ex)
            {
                MessageBox.Show("Could not find settings file. \n" + ex.ToString());
                Environment.Exit(0);
            }
            if (guiConfig.SelectSingleNode("/AppImporter/SCCMServer").InnerText == "Server01")
            {
                menuSettings.PerformClick();
            }

            //MessageBox.Show(guiConfig.SelectSingleNode("/AppImporter/SCCMServer").InnerText.ToString());
        }
 
        private static string RandomString(int size)
        {
            //int size = 8;
            Random r = new Random();
            string legalChars = "123456789abcdefghijklmnopqrstuvwxzyABCDEFGHIJKLMNOPQRSTUVWXZY";
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < size; i++)
                sb.Append(legalChars.Substring(r.Next(0, legalChars.Length - 1), 1));
            return sb.ToString();
        }

        private void Ballontip(string title, string text, ToolTipIcon icontype, int displaytime)
        {
            NotifyIcon ballon = new NotifyIcon();
            ballon.Icon = this.Icon; //MessageBoxIcon.Information

            ballon.BalloonTipIcon = icontype; //Valid are Info, Warning, Error
            ballon.BalloonTipTitle = title;
            ballon.BalloonTipText = text;
            ballon.Visible = true;
            ballon.ShowBalloonTip(displaytime);
        }

        #region MainForm Layout

        private void MainForm_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
        {
            e.Graphics.FillRegion(Brushes.WhiteSmoke, TitleBar);
            e.Graphics.FillRectangle(Brushes.WhiteSmoke, new Rectangle(0, 26, Width, 19));

            if (FileHot) e.Graphics.FillRectangle(SystemBrushes.Highlight, labelFile.Bounds);
            if (HelpHot) e.Graphics.FillRectangle(SystemBrushes.Highlight, labelHelp.Bounds);

            Pen BorderPen = new Pen(Color.Gainsboro, 2);
            BorderPen.Alignment = PenAlignment.Inset;
            //e.Graphics.DrawPath(BorderPen, FormShape);
            e.Graphics.DrawPath(BorderPen, OrgShape);
            BorderPen.Dispose();

            e.Graphics.SmoothingMode = SmoothingMode.HighQuality;

            StringFormat sf = new StringFormat(StringFormatFlags.NoWrap);
            sf.Trimming = StringTrimming.EllipsisCharacter;
            sf.Alignment = StringAlignment.Near;
            sf.LineAlignment = StringAlignment.Center;

            e.Graphics.DrawIcon(this.Icon, new Rectangle(10,4,16,16)); //, RectangleF.FromLTRB(4, 0, MinButton.GetBounds().X, 24));
            e.Graphics.DrawString(this.Text, Control.DefaultFont, Brushes.Gray, RectangleF.FromLTRB(24, 0, MinButton.GetBounds().X, 24), sf);

            if (ClosePress)
                e.Graphics.FillPath(Brushes.Gray, CloseButton);
            else
                e.Graphics.FillPath(Brushes.WhiteSmoke, CloseButton);

            if (MinPress)
                e.Graphics.FillPath(Brushes.Gray, MinButton);
            else
                e.Graphics.FillPath(Brushes.WhiteSmoke, MinButton);

            if (OverClose)
                e.Graphics.FillPath(Brushes.DodgerBlue, CloseButton);
            else
                e.Graphics.FillPath(Brushes.WhiteSmoke, CloseButton);

            if (OverMin)
                e.Graphics.FillPath(Brushes.DodgerBlue, MinButton);
            else
                e.Graphics.FillPath(Brushes.WhiteSmoke, MinButton);

            Font GlyphFont = new Font("marlett", Font.SizeInPoints, FontStyle.Bold, GraphicsUnit.Point);
            e.Graphics.DrawString("0", GlyphFont, Brushes.Black, MinButton.GetBounds(), sf);
            e.Graphics.DrawString("r", GlyphFont, Brushes.Black, CloseButton.GetBounds(), sf);
            GlyphFont.Dispose();

        }

        private void MainForm_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            ClosePress = CloseButton.IsVisible(e.X, e.Y) && e.Button == MouseButtons.Left;
            MinPress = MinButton.IsVisible(e.X, e.Y) && e.Button == MouseButtons.Left;
            FormDrag = TitleBar.IsVisible(e.X, e.Y) &&
            e.Button == MouseButtons.Left &&
                ClosePress == false && MinPress == false;

            if (FormDrag)
            {
                this.Capture = false;
                Message msg = Message.Create(Handle, WM_NCLBUTTONDOWN, (IntPtr)HT_CAPTION, IntPtr.Zero);
                WndProc(ref msg);
            }
        }

        private void MainForm_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            OverClose = CloseButton.IsVisible(e.X, e.Y);
            OverMin = MinButton.IsVisible(e.X, e.Y);
            ClosePress = OverClose && e.Button == MouseButtons.Left;
            MinPress = OverMin && e.Button == MouseButtons.Left;

            if (OverClose && ClosePress == false)
                tt_Mainform.SetToolTip(this, "Close");
            else if (OverMin && MinPress == false)
                tt_Mainform.SetToolTip(this, "Minimize");
            else
                tt_Mainform.SetToolTip(this, "");

            Invalidate();

        }

        private void MainForm_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            bool OverClose, OverMin;
            OverClose = CloseButton.IsVisible(e.X, e.Y);
            OverMin = MinButton.IsVisible(e.X, e.Y);

            if (OverClose && ClosePress && e.Button == MouseButtons.Left)
                this.Close();
            if (OverMin && MinPress && e.Button == MouseButtons.Left)
                this.WindowState = FormWindowState.Minimized;

            if (e.Button == MouseButtons.Right && TitleBar.IsVisible(e.X, e.Y))
            {
                if (OverClose == false && OverMin == false)
                {
                    const int WM_GETSYSMENU = 0x313;
                    if (e.Button == MouseButtons.Right)
                    {
                        Point pos = this.PointToScreen(new Point(e.X, e.Y));
                        IntPtr hPos = (IntPtr)((int)((pos.Y * 0x10000) | (pos.X & 0xFFFF)));
                        Message msg = Message.Create(this.Handle, WM_GETSYSMENU, IntPtr.Zero, hPos);
                        WndProc(ref msg);
                    }
                }
            }

            ClosePress = false;
            MinPress = false;
            FormDrag = false;

            Invalidate();

        }

        private Region TitleBar
        {
            get 
            { 
                return new Region(new Rectangle(0, 0, Width, 46)); 
            }
        }

        private GraphicsPath CloseButton
        {
            get
            {
                GraphicsPath gp = new GraphicsPath();
                //gp.AddEllipse(new Rectangle(Width - 26, 3, 18, 18));
                gp.AddRectangle(new Rectangle(Width - 26, 3, 18, 18));
                return gp;
            }
        }

        private GraphicsPath SettingsButton
        {
            get
            {
                GraphicsPath gp = new GraphicsPath();
                //gp.AddEllipse(new Rectangle(Width - 49, 3, 18, 18));
                gp.AddRectangle(new Rectangle(Width - 49, Height - 100, 18, 18));
                return gp;
            }
        }

        private GraphicsPath FormIcon
        {
            get
            {
                GraphicsPath gp = new GraphicsPath();
                gp.AddRectangle(new Rectangle(3,3,32,32));
                return gp;
            }
        }

        private GraphicsPath MinButton
        {
            get
            {
                GraphicsPath gp = new GraphicsPath();
                //gp.AddEllipse(new Rectangle(Width - 49, 3, 18, 18));
                gp.AddRectangle(new Rectangle(Width - 49, 3, 18, 18));
                return gp;
            }
        }

        private GraphicsPath OrgShape
        {
            get
            {
                GraphicsPath gp = new GraphicsPath();
                Rectangle r = ClientRectangle;
                gp.AddRectangle(r);
                return gp;
            }
        }

        private GraphicsPath FormShape
        {
            get
            {
                GraphicsPath gp = new GraphicsPath();
                Rectangle r = ClientRectangle;
                int radius = 12;

                gp.AddArc(r.Left, r.Top + 24, radius, radius, 180, 90);
                gp.AddArc(r.Left + 90 - radius, r.Top + 24 - radius, radius, radius, -270, -90);
                gp.AddArc(r.Left + 80, r.Top, radius, radius, 180, 90);
                gp.AddArc(r.Right - radius, r.Top, radius, radius, 270, 90);
                gp.AddArc(r.Right - radius, r.Bottom - radius, radius, radius, 0, 90);
                gp.AddArc(r.Left, r.Bottom - radius, radius, radius, 90, 90);
                gp.CloseFigure();

                return gp;
            }
        }

        private void MainForm_Resize(object sender, System.EventArgs e)
        {
            this.Region = new Region(OrgShape);
        }

        private void menuAbout_Click(object sender, System.EventArgs e)
        {
            //MessageBox.Show("SCCM 2012 Application Importer by Mattias Benninge (http://myitforum.com/myitforumwp/author/matbe/)", "About...", MessageBoxButtons.OK);
            MessageBox.Show("SCCM 2012 Application Importer by Mattias Benninge (https://sccmappimp.codeplex.com/)" + "\n" + "Version:" + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString(), "About...", MessageBoxButtons.OK,
                                MessageBoxIcon.Information, MessageBoxDefaultButton.Button1, 0, "https://sccmappimp.codeplex.com/documentation");
        }

        private void menuSettings_Click(object sender, System.EventArgs e)
        {
            this.Cursor = Cursors.WaitCursor;
            try
            {
                this.SettingsBrowseDialog = new Settings();
                this.SettingsBrowseDialog.ValueUpdated += new ValueUpdatedEventHandler(SettingsBrowseDialog_ValueUpdated);
                //ClientInstallDialog.openFileDialog1.InitialDirectory = @"\\" + oSMSClient.ManagementPoint;
                if (SettingsBrowseDialog.ShowDialog(this) == DialogResult.OK)
                {

                }
                //MessageBox.Show("Shaped Form Example!\nBy Mick Doherty (http://myitforum.com/myitforumwp/author/matbe/)", "About...", MessageBoxButtons.OK);
            }
            catch (SystemException ex)
            {
                MessageBox.Show(ex.ToString());
                //desktopAlert1.ShowAlert(ex.ToString());
            }
            finally
            {
                this.Cursor = Cursors.Default;
            }

            if (XMLSaved == "true")
            {
                guiConfig.Load(@".\Settings.xml"); // .Load(@"..\..\Settings.xml");
                tb_prefix.Text = guiConfig.SelectSingleNode("/AppImporter/Prefix").InnerText;
                //MessageBox.Show(guiConfig.SelectSingleNode("/AppImporter/SCCMServer").InnerText.ToString());

                // Recreate the connection to SCCM after settings have been updated
                try
                {
                    //Initialize(guiConfig.SelectSingleNode("/AppImporter/SCCMServer").InnerText.ToString());
                    this.SCCMWQLConnection = this.Connect(guiConfig.SelectSingleNode("/AppImporter/SCCMServer").InnerText);

                }
                catch (Exception ex)
                {
                    MessageBox.Show("Could not connect to server, wrong credentials or servername?");
                    Ballontip("Error", ex.Message, ToolTipIcon.Error, 6000);
                    //MessageBox.Show(ex.ToString());
                }

                GetSMSIdentID((WqlConnectionManager)SCCMWQLConnection);


                XMLSaved = "";
            }

        }

        private void SettingsBrowseDialog_ValueUpdated(object sender, ValueUpdatedEventArgs e)
        {
            // Update the text box on this form (the parent) with the new value
            string s = e.NewValue;
            //MessageBox.Show(s);

            XMLSaved = s;
            //string[] advfldarr = s.Split(';');

            //this.tb_advfldid.Text = advfldarr[0];
            //this.tb_advfldname.Text = advfldarr[1];

            //this.tb_collid.Text = e.NewValue;
        }

        private void menuExit_Click(object sender, System.EventArgs e)
        {
            System.Windows.Forms.Application.Exit();
        }

        private void labelHelp_MouseEnter(object sender, System.EventArgs e)
        {
            HelpHot = true;
            labelHelp.ForeColor = SystemColors.HighlightText;
            Invalidate();
        }

        private void labelHelp_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            HelpActive = true;
            contextMenu2.Show(labelHelp, new Point(0, labelHelp.Height));
            HelpActive = false;
            labelHelp.ForeColor = SystemColors.MenuText;
            Invalidate();
        }

        private void labelHelp_MouseLeave(object sender, System.EventArgs e)
        {
            if (HelpActive == false)
            {
                HelpHot = false;
                labelHelp.ForeColor = SystemColors.MenuText;
            }
            Invalidate();
        }

        private void labelFile_MouseEnter(object sender, System.EventArgs e)
        {
            FileHot = true;
            labelFile.ForeColor = SystemColors.HighlightText;
            Invalidate();
        }

        private void labelFile_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            FileActive = true;
            contextMenu1.Show(labelFile, new Point(0, labelFile.Height));
            FileActive = false;
            labelFile.ForeColor = SystemColors.MenuText;
            Invalidate();
        }

        private void labelFile_MouseLeave(object sender, System.EventArgs e)
        {
            if (FileActive == false)
            {
                FileHot = false;
                labelFile.ForeColor = SystemColors.MenuText;
            }
            Invalidate();
        }

        private void bt_highlight_MouseEnter(object sender, System.EventArgs e)
        {
            //
            // Set the font and forecolor when the cursor hovers over a label.
            //
            Label lbl = (Label)sender;
            lbl.BackColor = System.Drawing.Color.DodgerBlue;
        }

        private void bt_highlight_MouseLeave(object sender, System.EventArgs e)
        {
            //
            // Reset the font and forecolor when the mouse stops hovering over a label.
            //
            Label lbl = (Label)sender;
            lbl.BackColor = System.Drawing.Color.Gainsboro;
        }
 
        private bool Sizing = false;
        private Point SizeOffset = Point.Empty;

        private void labelResize_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            Sizing = true;
            SizeOffset = new Point(this.Right - Cursor.Position.X, this.Bottom - Cursor.Position.Y);
        }

        private void labelResize_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            if (Sizing)
            {
                //Clip cursor to dissallow sizing of form below 250x100
                Rectangle ClipRectangle = RectangleToScreen(new Rectangle(250, 100, Width, Height));
                ClipRectangle.Offset(SizeOffset);
                Cursor.Clip = ClipRectangle;
                this.Size = new Size(Cursor.Position.X + SizeOffset.X - Location.X, Cursor.Position.Y + SizeOffset.Y - Location.Y);
            }
        }

        private void labelResize_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            Sizing = false;
            Cursor.Clip = Rectangle.Empty;
        }

        private void cb_CreateColl_CheckedChanged(object sender, EventArgs e)
        {
            if (cb_CreateColl.Checked == true)
            {
                tb_collid.Enabled = true;
                tb_collid.BackColor = System.Drawing.Color.White;
                tb_collname.Enabled = true;
                tb_collname.BackColor = System.Drawing.Color.White;
            }
            else
            {
                tb_collid.Enabled = false;
                tb_collid.BackColor = SystemColors.Control;
                tb_collname.Enabled = false;
                tb_collname.BackColor = SystemColors.Control;

            }
        }

        private void cb_CreateADGroup_CheckedChanged(object sender, EventArgs e)
        {

            if (cb_CreateADGroup.Checked == true)
                tb_adname.Enabled = true;
            else
                tb_adname.Enabled = false;
        }

        private void cb_CreatePkg_CheckedChanged(object sender, EventArgs e)
        {
            if (cb_CreatePkg.Checked == true)
            {
                tb_appfldid.Enabled = true;
                tb_appfldid.BackColor = System.Drawing.Color.White;
                tb_appfldname.Enabled = true;
                tb_appfldname.BackColor = System.Drawing.Color.White;
            }
            else
            {
                tb_appfldid.Enabled = false;
                tb_appfldid.BackColor = SystemColors.Control;
                tb_appfldname.Enabled = false;
                tb_appfldname.BackColor = SystemColors.Control;
            }
        }

        #endregion

        #region Form Functions
        private void openFileDialog1_FileOk(object sender, CancelEventArgs e)
        {

        }

        private void bt_browsemsi_Click(object sender, EventArgs e)
        {
            Type installerType = Type.GetTypeFromProgID("WindowsInstaller.Installer");
            installer = Activator.CreateInstance(installerType) as WindowsInstaller.Installer;

            string MSIStartPath = guiConfig.SelectSingleNode("/AppImporter/AppFldRoot").InnerText;
            openFileDialog1.InitialDirectory = MSIStartPath;
            DialogResult result = openFileDialog1.ShowDialog(); // Show the dialog and get result.
            if (result == DialogResult.OK) // Test result.
            {

                //    string directoryPath = Path.GetDirectoryName(openFileDialog1.FileName);
                strmsipath = Path.GetDirectoryName(openFileDialog1.FileName);
                strmsifilename = Path.GetFileName(openFileDialog1.FileName);
                tb_msipath.Text = openFileDialog1.FileName;
                tb_msiname.Enabled = true;
                tb_msiversion.Enabled = true;
                tb_msiManufacturer.Enabled = true;
                tb_mstpath.Enabled = true;
                //bt_browsemst.Enabled = true;

                try
                {
                    db = installer.OpenDatabase(openFileDialog1.FileName, WI.MsiOpenDatabaseMode.msiOpenDatabaseModeReadOnly);
                }
                catch (SystemException ex)
                {
                    Ballontip("Error", ex.Message, ToolTipIcon.Error, 6000);
                    //desktopAlert1.ShowAlert(ex.ToString());
                }

                WI.StringList cps = installer.Components;
                WI.MsiEvaluateCondition cond = db.get_TablePersistent("Shortcut");
                if (cond != WI.MsiEvaluateCondition.msiEvaluateConditionTrue)
                {
                    MessageBox.Show("Error: No shortcut data in MSI");
                }

                WI.SummaryInfo si = db.get_SummaryInformation(0);

                StringBuilder sb = new StringBuilder();
                for (int p = 1; p < si.PropertyCount; p++)
                {
                    object prop = si.get_Property(p);
                    if (prop != null)
                        sb.AppendLine(Enum.GetName(typeof(PID), p) +
                          ": " + prop.ToString());
                }
                //MessageBox.Show(sb.ToString());


                string strMSIProductName = null;
                string strMSIProductVersion = null;
                string strMSIProductCode = null;
                string strMSIManufacturer = si.get_Property(4).ToString();

                tb_msiManufacturer.Text = strMSIManufacturer;

                // Get strMSIProductName
                Cursor = Cursors.WaitCursor;
                try
                {
                    WI.View view = null;
                    try
                    {
                        view = db.OpenView("Select `Property`,`Value` From Property WHERE `Property` = 'ProductName'");
                    }
                    catch (Exception exp)
                    {
                        MessageBox.Show("[" + exp.Source + "] Description: " + exp.Message);
                        return;
                    }
                    view.Execute(null);
                    WI.Record fetch = null;

                    do
                    {
                        fetch = view.Fetch();
                        if (fetch == null) break;
                        strMSIProductName = fetch.get_StringData(2);

                        Marshal.ReleaseComObject(fetch);

                    } while (true);

                    Marshal.ReleaseComObject(view);

                    tb_msiname.Text = strMSIProductName;


                }
                finally
                {
                    Cursor = Cursors.Default;
                }

                Cursor = Cursors.WaitCursor;
                try
                {
                    WI.View view = null;
                    try
                    {
                        view = db.OpenView("Select `Property`,`Value` From Property WHERE `Property` = 'ProductVersion'");
                    }
                    catch (Exception exp)
                    {
                        MessageBox.Show("[" + exp.Source + "] Description: " + exp.Message);
                        return;
                    }
                    view.Execute(null);
                    WI.Record fetch = null;

                    do
                    {
                        fetch = view.Fetch();
                        if (fetch == null) break;
                        strMSIProductVersion = fetch.get_StringData(2);

                        Marshal.ReleaseComObject(fetch);

                    } while (true);

                    Marshal.ReleaseComObject(view);

                    tb_msiversion.Text = strMSIProductVersion;

                }

                finally
                {
                    Cursor = Cursors.Default;
                }

                Cursor = Cursors.WaitCursor;
                try
                {
                    WI.View view = null;
                    try
                    {
                        view = db.OpenView("Select `Property`,`Value` From Property WHERE `Property` = 'ProductCode'");
                    }
                    catch (Exception exp)
                    {
                        MessageBox.Show("[" + exp.Source + "] Description: " + exp.Message);
                        return;
                    }
                    view.Execute(null);
                    WI.Record fetch = null;

                    do
                    {
                        fetch = view.Fetch();
                        if (fetch == null) break;
                        strMSIProductCode = fetch.get_StringData(2);

                        Marshal.ReleaseComObject(fetch);

                    } while (true);

                    Marshal.ReleaseComObject(view);

                    MSIGuid = tb_msiguid.Text = strMSIProductCode;

                }

                finally
                {
                    Cursor = Cursors.Default;
                }


                /*if (this.MSIGuidExist())
                {
                
                    tb_msiname.Enabled = false;
                    tb_msiversion.Enabled = false;
                    tb_msiManufacturer.Enabled = false;
                    tb_mstpath.Enabled = false;
                    bt_browsemst.Enabled = false;
                    bt_import.Enabled = false;
                    MessageBox.Show("WARNING! This program already exists!" + Environment.NewLine + "Import is not possible with duplicate GUIDs");
                }
    */
            }

            /*/ Get Column names
            string tableName = "Property";
            WindowsInstaller.View v = db.OpenView("SELECT `Value` FROM Property WHERE `Property` = 'ProductName' ");
            Record r = null;
            v.Execute(r);
            r = v.Fetch();
            */


            //toolStripStatusLabel1.Text = r.ToString() ;
            Console.WriteLine(result); // <-- For debugging use only.
        }

        private void bt_browsemst_Click(object sender, EventArgs e)
        {
            openFileDialog2.InitialDirectory = strmsipath;
            DialogResult result = openFileDialog2.ShowDialog(); // Show the dialog and get result.
            if (result == DialogResult.OK) // Test result.
            {

                //    string directoryPath = Path.GetDirectoryName(openFileDialog1.FileName);
                strmstfilename = Path.GetFileName(openFileDialog2.FileName);
                tb_mstpath.Text = strmstfilename;
            }
        }

        private void bt_browseColFld_Click(object sender, EventArgs e)
        {
            this.Cursor = Cursors.WaitCursor;

            try
            {
                this.CollectionBrowseDialog = new CollectionBrowse();
                this.CollectionBrowseDialog.ValueUpdated += new ValueUpdatedEventHandler(CollectionBrowseDialog_ValueUpdated);
                //ClientInstallDialog.openFileDialog1.InitialDirectory = @"\\" + oSMSClient.ManagementPoint;
                if (CollectionBrowseDialog.ShowDialog(this) == DialogResult.OK)
                {

                }
            }
            catch (SystemException ex)
            {
                Ballontip("Error", ex.Message, ToolTipIcon.Error, 6000);
                //desktopAlert1.ShowAlert(ex.ToString());
            }
            finally
            {
                this.Cursor = Cursors.Default;
            }
        }

        private void CollectionBrowseDialog_ValueUpdated(object sender, ValueUpdatedEventArgs e)
        {
            // Update the text box on this form (the parent) with the new value
            string s = e.NewValue;
            //MessageBox.Show(s);
            string[] collfldarr = s.Split(';');

            this.tb_collid.Text = collfldarr[0];
            this.tb_collname.Text = collfldarr[1];

            //this.tb_collid.Text = e.NewValue;
        }

        private void bt_browsePkgFld_Click(object sender, EventArgs e)
        {
            this.Cursor = Cursors.WaitCursor;

            try
            {
                this.AppfolderBrowseDialog = new AppfolderBrowse();
                this.AppfolderBrowseDialog.ValueUpdated += new ValueUpdatedEventHandler(AppfolderBrowseDialog_ValueUpdated);
                //ClientInstallDialog.openFileDialog1.InitialDirectory = @"\\" + oSMSClient.ManagementPoint;
                if (AppfolderBrowseDialog.ShowDialog(this) == DialogResult.OK)
                {

                }
            }
            catch (SystemException ex)
            {
                Ballontip("Error", ex.Message, ToolTipIcon.Error, 6000);
                //desktopAlert1.ShowAlert(ex.ToString());
            }
            finally
            {
                this.Cursor = Cursors.Default;
            }
        }

        private void AppfolderBrowseDialog_ValueUpdated(object sender, ValueUpdatedEventArgs e)
        {
            // Update the text box on this form (the parent) with the new value
            string s = e.NewValue;
            //MessageBox.Show(s);
            string[] pkgfldarr = s.Split(';');

            this.tb_appfldid.Text = pkgfldarr[0];
            this.tb_appfldname.Text = pkgfldarr[1];

            //this.tb_collid.Text = e.NewValue;
        }

        private void txt_TextChanged(object sender, System.EventArgs e)
        {
            checklength();
            UpdateADName();
        }

        private void UpdateADName()
        {
            if (tb_prefix.Text == "")
            {
                tb_adname.Text = (tb_msiname.Text + " " + tb_msiversion.Text);
            }
            else
            {
                tb_adname.Text = (tb_prefix.Text + "-" + tb_msiname.Text + " " + tb_msiversion.Text);
            }
        }

        private void checklength()
        {
            Int32 pkglen = tb_prefix.Text.Length + tb_msiname.Text.Length + tb_msiversion.Text.Length;
            lb_pkglen.Text = (tb_prefix.Text.Length + tb_msiname.Text.Length + tb_msiversion.Text.Length).ToString();
            if (pkglen > 46)
            {
                bt_import.Enabled = false;
            }
            else
            {
                bt_import.Enabled = true;
            }
        }

        private void bt_import_Click(object sender, EventArgs e)
        {
            this.Cursor = Cursors.WaitCursor;
            try
            {
                if (cb_CreateColl.Checked == true)
                    CreateSubCollection((WqlConnectionManager)SCCMWQLConnection);

                if (cb_CreateADGroup.Checked == true)
                    CreateADGroup(tb_adname.Text); // Create AD-Group |Working

                SCCMApplication();
            }
            catch (SystemException ex)
            {
                Ballontip("Error", ex.Message, ToolTipIcon.Error, 6000);
            }
            finally
            {
                this.Cursor = Cursors.Default;
            }


        }

        #endregion Form Functions

        public WqlConnectionManager Connect(string serverName) //, string userName, string userPassword)

        {
            try
            {
                SmsNamedValuesDictionary namedValues = new SmsNamedValuesDictionary();
                WqlConnectionManager connection = new WqlConnectionManager(namedValues);
                if (System.Net.Dns.GetHostName().ToUpper() == serverName.ToUpper())
                {
                    connection.Connect(serverName);
                }
                else
                {
                    connection.Connect(serverName);//, userName, userPassword);

                }
                return connection;
            }
            catch (SmsException ex)
            {
                Console.WriteLine("Failed to Connect. Error: " + ex.Message);
                return null;
            }
            catch (UnauthorizedAccessException ex)
            {
                Console.WriteLine("Failed to authenticate. Error:" + ex.Message);
                return null;
            }
        }

        #region MSI Functions
        WI.Database db;
        WI.Installer installer;


        /// <summary>Summary properties for installation packages, 
        ///  transforms, and patches are described in the 
        ///  following tables. </summary>
        /// <remarks> 
        ///  [Summary Property Descriptions (Windows)]
        ///  http://msdn.microsoft.com/en-us/library/aa372049(VS.85).aspx
        /// </remarks>
        enum PID
        {
            DICTIONARY = 0,
            CODEPAGE, TITLE, SUBJECT,
            AUTHOR, KEYWORDS, COMMENTS, TEMPLATE,
            LASTAUTHOR, REVNUMBER, EDITTIME,
            LASTPRINTED, CREATE_DTM, LASTSAVE_DTM,
            PAGECOUNT, WORDCOUNT, CHARCOUNT,
            THUMBNAIL, APPNAME, SECURITY
        }

        #region Possible bindings to MSI.dll APIs
        const string MSI_DLL = "MSI.dll";

        public partial class NativeMethods
        {
            /// <summary>The <c>MsiOpenPackage</c> function opens a package for use 
            ///    with the functions that access the product database. 
            ///    The <see cref="MsiCloseHandle"/> function must be called with 
            ///    the handle when the handle is no longer needed.</summary>
            /// <param name="path">Specifies the path to the package. </param>
            /// <param name="handle">Specifies the path to the package. </param>
            /// <returns>
            /// <para><see cref="MsiError.Success"/>  The function succeeded.</para>
            /// <para><see cref="MsiError.BadConfiguration"/>  The configuration data is corrupt.</para>
            /// <para><see cref="MsiError.InstallFailure"/>  The product could not be opened.</para>
            /// <para><see cref="MsiError.InstallRemoteProhibited"/>  Windows Installer does not permit installation from a Remote Desktop Connection.</para>
            /// <para><see cref="MsiError.InvalidParameter"/>  One of the parameters was invalid.</para>
            /// </returns>
            /// <remarks>
            /// [MsiOpenPackage Function (Windows)]
            /// http://msdn.microsoft.com/en-us/library/aa370339.aspx
            /// </remarks>
            [DllImport(MSI_DLL, CharSet = CharSet.Auto)]
            extern static public MsiError MsiOpenPackage(string path, out IntPtr handle);

            [DllImport(MSI_DLL, EntryPoint = "MsiSummaryInfoGetProperty")]
            public static extern uint MsiSummaryInfoGetProperty(
              [In()] IntPtr hSummaryInfo,
              uint uiProperty,
              [Out()] out uint puiDataType,
              [Out()] out int piValue,
              [Out()] out FILETIME pftValue,
              [Out()] 
        [MarshalAs(UnmanagedType.LPTStr)] StringBuilder szValueBuf,
        ref uint pcchValueBuf);

            #region MsiError
            /// <summary>Interner enum der MSI Fehelr.</summary>
            public enum MsiError : uint
            {
                /// <summary>No error occured.</summary>
                NoError = 0,
                /// <summary>The operation was successful.</summary>
                Success = 0,
                /// <summary>The system cannot find the file specified.</summary>
                FileNotFound = 2,
                /// <summary>Access is denied.</summary>
                AccessDenied = 5,
                /// <summary>The handle is invalid.</summary>
                InvalidHandle = 6,
                /// <summary>Not enough storage is available to process this command.</summary>
                NotEnoughMemory = 8,
                /// <summary>The data is invalid.</summary>
                InvalidData = 13,
                /// <summary>Not enough storage is available to complete this operation.</summary>
                OutOfMemory = 14,
                /// <summary>The parameter is incorrect.</summary>
                InvalidParameter = 87,
                /// <summary>The system cannot open the device or file specified.</summary>
                OpenFailed = 110,
                /// <summary>There is not enough space on the disk.</summary>
                DiskFull = 112,
                /// <summary>This function is not available for this platform. It is only available on Windows 2000 and Windows XP with Window Installer version 2.0.</summary>
                CallNotImplemented = 120,
                /// <summary>The specified path is invalid.</summary>
                BadPathName = 161,
                /// <summary>No data is available.</summary>
                NoData = 232,
                /// <summary>More data is available.</summary>
                MoreData = 234,
                /// <summary>No more data is available.</summary>
                NoMoreItems = 259,
                /// <summary>The directory name is invalid.</summary>
                Directory = 267,
                /// <summary>The volume for a file has been externally altered so that the opened file is no longer valid.</summary>
                FileInvalid = 1006,
                /// <summary>This error code only occurs when using Windows Installer version 2.0 and Windows XP. If Windows Installer determines a product may be incompatible with the current operating system, it displays a dialog box informing the user and asking whether to try to install anyway. This error code is returned if the user chooses not to try the installation.</summary>
                AppHelpBlock = 1259,
                /// <summary>The Windows Installer service could not be accessed.</summary>
                InstallServiceFailure = 1601,
                /// <summary>The user cancels installation.</summary>
                InstallUserExit = 1602,
                /// <summary>A fatal error occurred during installation.</summary>
                InstallFailure = 1603,
                /// <summary>Installation suspended, incomplete.</summary>
                InstallSuspend = 1604,
                /// <summary>This action is only valid for products that are currently installed.</summary>
                UnknownProduct = 1605,
                /// <summary>The feature identifier is not registered.</summary>
                UnknownFeature = 1606,
                /// <summary>The component identifier is not registered.</summary>
                UnknownComponent = 1607,
                /// <summary>This is an unknown property.</summary>
                UnknownProperty = 1608,
                /// <summary>The handle is in an invalid state.</summary>
                InvalidHandleState = 1609,
                /// <summary>The configuration data for this product is corrupt.</summary>
                BadConfiguration = 1610,
                /// <summary>The component qualifier not present.</summary>
                IndexAbsent = 1611,
                /// <summary>The installation source for this product is not available. Verify that the source exists and that you can access it.</summary>
                InstallSourceAbsent = 1612,
                /// <summary>This installation package cannot be installed by the Windows Installer service. You must install a Windows service pack that contains a newer version of the Windows Installer service.</summary>
                InstallPackageVersion = 1613,
                /// <summary>The product is uninstalled.</summary>
                ProductUninstalled = 1614,
                /// <summary>The SQL query syntax is invalid or unsupported.</summary>
                BadQuerySyntax = 1615,
                /// <summary>The record field does not exist.</summary>
                InvalidField = 1616,
                /// <summary>Another installation is already in progress.</summary>
                InstallAlreadyRunning = 1618,
                /// <summary>This installation package could not be opened. Verify that the package exists and is accessible, or contact the application vendor to verify that this is a valid Windows Installer package.</summary>
                InstallPackageOpenFailed = 1619,
                /// <summary>This installation package could not be opened. Contact the application vendor to verify that this is a valid Windows Installer package.</summary>
                InstallPackageInvalid = 1620,
                /// <summary>There was an error starting the Windows Installer service user interface. </summary>
                InstallUIFailure = 1621,
                /// <summary>There was an error opening installation log file. Verify that the specified log file location exists and is writable.</summary>
                InstallLogFailure = 1622,
                /// <summary>This language of this installation package is not supported by your system.</summary>
                InstallLanguageUnsupported = 1623,
                /// <summary>There was an error applying transforms. Verify that the specified transform paths are valid.</summary>
                InstallTransformFailure = 1624,
                /// <summary>This installation is forbidden by system policy.</summary>
                InstallPackageRejected = 1625,
                /// <summary>The function could not be executed.</summary>
                FunctionNotCalled = 1626,
                /// <summary>The function failed during execution.</summary>
                FunctionFailed = 1627,
                /// <summary>An invalid or unknown table was specified.</summary>
                InvalidTable = 1628,
                /// <summary>The data supplied is the wrong type.</summary>
                DatatypeMismatch = 1629,
                /// <summary>Data of this type is not supported.</summary>
                UnsupportedType = 1630,
                /// <summary>The Windows Installer service failed to start.</summary>
                CreateFailed = 1631,
                /// <summary>The Temp folder is either full or inaccessible. Verify that the Temp folder exists and that you can write to it.</summary>
                InstallTempUnwritable = 1632,
                /// <summary>This installation package is not supported on this platform.</summary>
                InstallPlatformUnsupported = 1633,
                /// <summary>Component is not used on this machine.</summary>
                InstallNotUsed = 1634,
                /// <summary>This patch package could not be opened.</summary>
                PatchPackageOpenFailed = 1635,
                /// <summary>This patch package could not be opened</summary>
                PatchPackageInvalid = 1636,
                /// <summary>This patch package cannot be processed by the Windows Installer service.</summary>
                PatchPackageUnsupported = 1637,
                /// <summary>Another version of this product is already installed. Installation of this version cannot continue. To configure or remove the existing version of this product, use Add/Remove Programs in Control Panel.</summary>
                ProductVersion = 1638,
                /// <summary>Invalid command line argument. Consult the Windows Installer SDK for detailed command-line help.</summary>
                InvalidCommandLine = 1639,
                /// <summary>Installation from a Terminal Server client session is not permitted for the current user.</summary>
                InstallRemoteDisallowed = 1640,
                /// <summary>The installer has initiated a restart. This error code is not available on Windows Installer version 1.0.</summary>
                SuccessRebootInitiated = 1641,
                /// <summary>The installer cannot install the upgrade patch because the program being upgraded may be missing or the upgrade patch updates a different version of the program. Verify that the program to be upgraded exists on your computer and that you have the correct upgrade patch. This error code is not available on Windows Installer version 1.0.</summary>
                PatchTargetNotFound = 1642,
                /// <summary>The patch package is not permitted by system policy. This error code is available with Windows Installer versions 2.0.</summary>
                InstallTransformRejected = 1643,
                /// <summary>One or more customizations are not permitted by system policy. This error code is available with Windows Installer versions 2.0.</summary>
                InstallRemoteProhibited = 1644,
                /// <summary>The specified datatype is invalid.</summary>
                InvalidDataType = 1804,
                /// <summary>The specified username is invalid.</summary>
                BadUserName = 2202,
                /// <summary>A restart is required to complete the install. This does not include installs where the ForceReboot action is run. This error code is not available on Windows Installer version 1.0.</summary>
                SucessRebootRequired = 3010,
                /// <summary>Unspecified error.</summary>
                E_Fail = 0x80004005,
            }
            #endregion

            [DllImportAttribute(MSI_DLL, EntryPoint = "MsiSetProperty")]
            public static extern uint MsiSetProperty(
              [In()] IntPtr hInstall,
              [In()] [MarshalAs(UnmanagedType.LPTStr)] string szName,
              [In()] [MarshalAs(UnmanagedType.LPTStr)] string szValue);
        }

        #endregion
        #endregion MSI Functions

        #region AD-Functions

        private object CreateADGroup(string strName)
        {
            try
            {
                DirectoryEntry objGroup = new DirectoryEntry("LDAP://" + guiConfig.SelectSingleNode("/AppImporter/GroupOU").InnerText);
                DirectoryEntry objGroup2 = objGroup.Children.Add("CN=" + strName, "group");
                objGroup2.Properties["groupType"].Value = "-2147483646"; // "-2147483644";
                objGroup2.Properties["SamAccountName"].Value = strName;
                if (guiConfig.SelectSingleNode("/AppImporter/ADDescription").InnerText != "false")
                    objGroup2.Properties["info"].Value = "Created " + DateTime.Now.ToString() + " by " + SystemInformation.UserName + " using AppImporter" + Environment.NewLine + tb_comment.Text;
                objGroup2.CommitChanges();
                objGroup.Close();
                //this.StatusLine("Group: " + strName + " Created in Active Directory");

                //IADs
                DirectoryEntry objSecurityDescriptor = new DirectoryEntry("ntSecurityDescriptor");
            }
            catch (SystemException ex)
            {
                Ballontip("Error", ex.Message, ToolTipIcon.Error, 6000);
                /*
                ProjectData.SetProjectError(exception1);
                Exception exception = exception1;
                this.StatusLine("Group: " + strName + " Creation Failed. ");
                if (exception.Message.Contains("The object already exists"))
                {
                    this.StatusLine("Group already exists.");
                }
                else if (exception.Message.Contains("There is no such object on the server"))
                {
                    this.StatusLine("Please check OU setting");
                }
                else
                {
                    this.StatusLine("Unexpected Error.");
                }
                this.StatusLine("Detailed Error Message:" + exception.Message);
                this.StatusLine("Operation Aborted");
                ProjectData.ClearProjectError();
                return 1;
                */
            }
            return 0;
        }

        #endregion AD-Functions

        #region SCCM Functions
        public void GetSMSIdentID(WqlConnectionManager SCCMWQLConnection)
        {

            try
            {
                IResultObject result = SCCMWQLConnection.ExecuteMethod("SMS_Identification", "GetSiteID", null);
                System.Collections.Generic.Dictionary<string, string>.Enumerator eDict = result.Properties.PropertyList.GetEnumerator();
                foreach (IResultObject queryResult in result)
                {
                    while (eDict.MoveNext())
                    {
                        if (eDict.Current.Key.ToString() == "SiteID")
                            strSiteID = "ScopeId_" + eDict.Current.Value.ToString().Substring(1, (eDict.Current.Value.Length - 2)).ToString();
                        //MessageBox.Show(eDict.Current.Value.ToString().Substring(1, (eDict.Current.Value.Length - 2)).ToString());
                        //MessageBox.Show("Key=" + eDict.Current.Key.ToString() + " Value="+eDict.Current.Value.ToString());  
                    }
                }
            }
            catch (SystemException ex)
            {
                Ballontip("Error", ex.Message, ToolTipIcon.Error, 6000);
            }
            finally { }

        }

        public void CreateSubCollection(WqlConnectionManager SCCMWQLConnection)
        {
            
            //string strCollection = tb_prefix.Text + "-" + tb_msiname.Text + " " + tb_msiversion.Text;
            
            string strCollection = tb_adname.Text;

            string queryForBaseRule = "select SMS_R_System.ResourceID,SMS_R_System.ResourceType,SMS_R_System.Name,SMS_R_System.SMSUniqueIdentifier,SMS_R_System.ResourceDomainORWorkgroup,SMS_R_System.Client from SMS_R_System where SystemGroupName ='" + guiConfig.SelectSingleNode("/AppImporter/ADDomain").InnerText + "\\\\" + tb_adname.Text + "'";

            try
            {
                IResultObject newCollection = SCCMWQLConnection.CreateInstance("SMS_Collection");


                newCollection["Comment"].StringValue = "Created " + DateTime.Now.ToString() + " by " + SystemInformation.UserName + " using AppImporter";
                newCollection["Name"].StringValue = strCollection;
                newCollection["OwnedByThisSite"].BooleanValue = true;
                newCollection["LimitToCollectionID"].StringValue = guiConfig.SelectSingleNode("/AppImporter/LimitingCollection").InnerText;

                // Save the new collection and the collection path for later.
                newCollection.Put();
                newCollection.Get();

                advCollectionID = newCollection["CollectionID"].StringValue;

                IResultObject recurInterval = SCCMWQLConnection.CreateEmbeddedObjectInstance("SMS_ST_RecurInterval");

                //Set Token = objWMIService.Get("Sms_St_RecurInterval")
                recurInterval["DaySpan"].IntegerValue = 7;					// HourSpan (1-24), DaySpan(1-31) or MinuteSpan(1-60)
                recurInterval["StartTime"].DateTimeValue = DateTime.Now;

                // Creating array to use as a parameters for the WriteToString method.
                List<IResultObject> scheduleTokens = new List<IResultObject>();
                scheduleTokens.Add(recurInterval);


                newCollection.SetArrayItems("RefreshSchedule", scheduleTokens);
                newCollection["RefreshType"].IntegerValue = Convert.ToInt32(guiConfig.SelectSingleNode("/AppImporter/CollUpdateType").InnerText);	//  2 = Periodic, 6 = Incremental updates 
                newCollection.Put();

                scheduleTokens.Clear();

                // Validate the query.
                Dictionary<string, object> validateQueryParameters = new Dictionary<string, object>();
                validateQueryParameters.Add("WQLQuery", queryForBaseRule);
                IResultObject result = SCCMWQLConnection.ExecuteMethod("SMS_CollectionRuleQuery", "ValidateQuery", validateQueryParameters);

                // Create query rule.
                IResultObject newQueryRule = SCCMWQLConnection.CreateInstance("SMS_CollectionRuleQuery");
                newQueryRule["QueryExpression"].StringValue = queryForBaseRule;
                newQueryRule["RuleName"].StringValue = "Base Query Generated By script";

                // Add the rule. Although not used in this sample, QueryID contains the query identifier.                   
                Dictionary<string, object> addMembershipRuleParameters = new Dictionary<string, object>();
                addMembershipRuleParameters.Add("collectionRule", newQueryRule);
                IResultObject queryID = newCollection.ExecuteMethod("AddMembershipRule", addMembershipRuleParameters);

                // Start collection evaluator.
                Dictionary<string, object> requestRefreshParameters = new Dictionary<string, object>();
                requestRefreshParameters.Add("IncludeSubCollections", false);
                newCollection.ExecuteMethod("RequestRefresh", requestRefreshParameters);

                // Move the created package to correct folder.
                if (tb_collid.Text != "")
                        if (Convert.ToInt32(tb_collid.Text) != 0)
                            MoveConsoleFolderItem((WqlConnectionManager)SCCMWQLConnection, newCollection["CollectionID"].StringValue, Convert.ToInt32(guiConfig.SelectSingleNode("/AppImporter/AppImpType").InnerText), 0, Convert.ToInt32(tb_collid.Text)); 


            }

            catch (SmsException ex)
            {
                Ballontip("Error","Failed to create collection. Error: " + ex.Message, ToolTipIcon.Error, 6000);
                // Console.WriteLine("Failed to create collection. Error: " + ex.Message);
                throw;
            }

        }

        private void SCCMApplication()
        {
            // A default scope must be defined to provide a logical identifier for yourself. This is a static property and only needs to be set once.
            Microsoft.ConfigurationManagement.ApplicationManagement.NamedObject.DefaultScope = "MyVendorId";
            Microsoft.ConfigurationManagement.ApplicationManagement.ObjectId objAppID = new Microsoft.ConfigurationManagement.ApplicationManagement.ObjectId(strSiteID, "Application_" + Guid.NewGuid().ToString());
            Microsoft.ConfigurationManagement.ApplicationManagement.Application application = new Microsoft.ConfigurationManagement.ApplicationManagement.Application(objAppID);

            // Must define the unlocalized title for the application
            application.Title = tb_adname.Text;
            //if (tb_comment.Text != "")
            //    application.Description = tb_comment.Text;

            // At least one AppDisplayInfo is required. This contains localized application details for showing up in in Software Center or the Application Catalog
            Microsoft.ConfigurationManagement.ApplicationManagement.AppDisplayInfo displayInfo = new Microsoft.ConfigurationManagement.ApplicationManagement.AppDisplayInfo();
            displayInfo.Language = "en-US";
            displayInfo.Title = tb_msiname.Text + tb_msiversion.Text;
            //displayInfo.Title = tb_msiname.Text;
            displayInfo.Publisher = tb_msiManufacturer.Text;

            // Add the AppDisplayInfo to the Application
            application.DisplayInfo.Add(displayInfo);

            application.DisplayInfo.DefaultLanguage = displayInfo.Language;

            //Microsoft.ConfigurationManagement.ApplicationManagement.appv

            // Create content definitions for the installer, this would point to the files that are deployed as part of the application's package
            // Also create a ContentRef, if this is not created the application will think the content is locally available and wont download the
            // content from the DP
            Microsoft.ConfigurationManagement.ApplicationManagement.Content content = Microsoft.ConfigurationManagement.ApplicationManagement.ContentImporter.CreateContentFromFolder(@"" + strmsipath + "");
            Microsoft.ConfigurationManagement.ApplicationManagement.ContentRef contentReference = new Microsoft.ConfigurationManagement.ApplicationManagement.ContentRef(content);

            // Various options for the content on the client machine
            content.OnFastNetwork = AM.ContentHandlingMode.Download;
            content.OnSlowNetwork = AM.ContentHandlingMode.Download;
            content.FallbackToUnprotectedDP = false;

            AM.MsiInstaller msiinstall = new AM.MsiInstaller();

            msiinstall.InstallCommandLine = "msiexec.exe /qb-! ALLUSERS=1 /i \"" + strmsifilename.ToString() + "\"";
            msiinstall.UninstallCommandLine = "msiexec.exe /x " + tb_msiguid.Text.ToString() + " /q";

            msiinstall.DetectionMethod = AM.DetectionMethod.ProductCode;
            msiinstall.ProductCode = tb_msiguid.Text;

            msiinstall.InstallContent = contentReference;
 

            AM.DeploymentType msiDT = new AM.DeploymentType(msiinstall, AM.MsiInstaller.TechnologyId, AM.NativeHostingTechnology.TechnologyId);
            if (tb_prefix.Text != "")
            {
                msiDT.Title = tb_prefix.Text + "-" + tb_msiname.Text + "-MSI";
            }
            else
            {
                msiDT.Title = tb_msiname.Text + "-MSI";
            }

            msiDT.Installer.Contents.Add(content);
            msiDT.Enabled = true;
            msiDT.Version = 1;

            // Add a Requirements Deployment rule for Primary user if enabled
            if (guiConfig.SelectSingleNode("/AppImporter/DeploymentReq").InnerText.ToString() == "True")
            {
                // Expression for the properties around the drive (in this case, must be system drive)  
                CustomCollection<ExpressionBase> PrimaryDeviceBool = new CustomCollection<ExpressionBase>();
                GlobalSettingReference PrimaryDeviceRef = new GlobalSettingReference("GLOBAL", "PrimaryDevice", DataType.Boolean, "PrimaryDevice_Setting_LogicalName", ConfigurationItemSettingSourceType.CIM);
                ConstantValue constant = new ConstantValue(guiConfig.SelectSingleNode("/AppImporter/PrimaryDeviceDeploymentReq").InnerText.ToString(), DataType.Boolean);
                PrimaryDeviceBool.Add(PrimaryDeviceRef);
                PrimaryDeviceBool.Add(constant);
                Expression PrimaryDeviceExp = new Expression(ExpressionOperator.IsEquals, PrimaryDeviceBool);

                // Outer expression that combines the previous expressions
                //CustomCollection<ExpressionBase> outerOperands = new CustomCollection<ExpressionBase>();
                //outerOperands.Add(PrimaryDeviceExp);
                //Expression fullExp = new Expression(ExpressionOperator.And, outerOperands);

                // Now build a rule and add it to the DT
                Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Rules.Rule rule = new Microsoft.SystemsManagementServer.DesiredConfigurationManagement.Rules.Rule("AIRule_" + Guid.NewGuid().ToString("B"), NoncomplianceSeverity.Critical, null, PrimaryDeviceExp);
                msiDT.Requirements.Add(rule);
            }

            //msiDT.Version = Convert.ToInt32(tb_msiversion.Text);
            application.DeploymentTypes.Add(msiDT);
            application.Version = 1;

            /*
            // Create an installer which will be used on the client to actually install the application
            ScriptInstaller installer = new ScriptInstaller();

            // Add the content to the Installer
            installer.Contents.Add(content);

            // The install command line is what's run on the client
            installer.InstallCommandLine = "MyInstaller.exe x y z";

            // Use product code detection to verify if the application was installed
            installer.DetectionMethod = DetectionMethod.ProductCode;
            installer.ProductCode = "{12345678-1234-5678-9012-345678901234}";

            // Now create the deployment type and bind it to the installer
            DeploymentType scriptDT = new DeploymentType(installer, ScriptInstaller.TechnologyId, NativeHostingTechnology.TechnologyId);
            scriptDT.Title = "My Application Installer";
            application.DeploymentTypes.Add(scriptDT);
            */
            // This app definition is what's written to the SMS Provider on the site server

            string appXml = SccmSerializer.SerializeToString(application, true);
            ManagementObject appInstance = null;
            ManagementPath path = null;
            ObjectGetOptions options = null;
            ManagementClass appClass = null;
            try
            {
                ManagementScope scope = new ManagementScope(@"\\" + guiConfig.SelectSingleNode("/AppImporter/SCCMServer").InnerText + @"\root\Sms\Site_" + guiConfig.SelectSingleNode("/AppImporter/SCCMSiteCode").InnerText);
                path = new ManagementPath("SMS_Application");
                options = new ObjectGetOptions();
                appClass = new ManagementClass(scope, path, options);
                appInstance = appClass.CreateInstance();
            }
            finally
            {
                appClass.Dispose();
            }

            appInstance.Properties["SDMPackageXML"].Value = appXml;
            appInstance.Put();
            appInstance.Get();

            // Dont assign App to a DP-Group if none have been choosen
            if (guiConfig.SelectSingleNode("/AppImporter/DistributionGroupID").InnerText.ToString() != "")
                AssignAppToDistributionPointGroup((WqlConnectionManager)SCCMWQLConnection, appInstance.Properties["ModelName"].Value.ToString());


            // Move the created package to correct folder.
            if (tb_appfldid.Text != "")
                if (Convert.ToInt32(tb_appfldid.Text) != 0)
                    MoveConsoleFolderItem((WqlConnectionManager)SCCMWQLConnection, appInstance.Properties["ModelName"].Value.ToString(), 6000, 0, Convert.ToInt32(tb_appfldid.Text));

            // ChangeMe cb_CreatePkg
            if (guiConfig.SelectSingleNode("/AppImporter/DistributionGroupID").InnerText.ToString() != "")
                if (cb_CreatePkg.Checked == true && advCollectionID != null)
                    CreateDeployment((WqlConnectionManager)SCCMWQLConnection, advCollectionID, appInstance.Properties["ModelID"].Value.ToString(), appInstance.Properties["CI_UniqueID"].Value.ToString(), appInstance.Properties["CI_ID"].Value.ToString(), appInstance.Properties["ModelName"].Value.ToString(), application.Title, tb_prefix.Text.ToString() + "-" + tb_msiname.Text.ToString() + "-UAI", "Created " + DateTime.Now.ToString() + " by " + SystemInformation.UserName + " using App Importer", 0, DateTime.Now, true);


        }

        public void AssignAppToDistributionPointGroup(WqlConnectionManager connection, string ModelName)
        {

            try
            {
                // Get the PackageID for the Application that is stored in SMS_CIContentPackage
                string query = "SELECT * FROM SMS_CIContentPackage WHERE ModelName='" + ModelName + "'";
                IResultObject result = connection.QueryProcessor.ExecuteQuery(query);

                string strPackageID = "";

                foreach (IResultObject r in result)
                {
                    strPackageID = r["PackageID"].StringValue;
                }

                Dictionary<string, object> parameters = new Dictionary<string, object>();
                string[] sourceItems = new string[1];
                // Only one item is being moved, the array size is 1.

                IResultObject dpGroup = connection.GetInstance(@"SMS_DistributionPointGroup.GroupID='" + guiConfig.SelectSingleNode("/AppImporter/DistributionGroupID").InnerText + "'");

                sourceItems[0] = strPackageID;
                parameters.Add("PackageIDs", sourceItems);
                dpGroup.ExecuteMethod("AddPackages", parameters);
            }

            catch (SmsException ex)
            {
                Ballontip("Error", "Failed to assign application to DP-Group. Error: " + ex.Message, ToolTipIcon.Error, 6000);
                //Console.WriteLine("Failed to create package. Error: " + ex.Message);
                throw;
            }
        }

        private void CreateDeployment(WqlConnectionManager connection, string existingCollectionID, string AppModelID, string UniqueID, String ArrayAssignedCIs, string existingPackageID, string existingProgramName, string newAdvertisementName, string newAdvertisementComment, int newAdvertisementFlags, DateTime newAdvertisementStartOfferDateTime, bool newAdvertisementStartOfferEnabled)
        {
            try
            {
                // Create new advertisement instance.
                IResultObject newDeployment = connection.CreateInstance("SMS_ApplicationAssignment");

                String[] tArray = ArrayAssignedCIs.Split(',');
                int[] newArrayAssignedCIs = new int[tArray.Length];
                
                for (int i = 0; i < tArray.Length; i++)
                {
                    newArrayAssignedCIs[i] = Convert.ToInt32(tArray[i]);
                }


                // Populate new advertisement values.
                // http://msdn.microsoft.com/en-us/library/hh949469.aspx
                newDeployment["ApplicationName"].StringValue = existingProgramName; //String
                newDeployment["ApplyToSubTargets"].BooleanValue = false; //Boolean
                newDeployment["AppModelID"].IntegerValue = Convert.ToInt32(AppModelID); //UInt32
                newDeployment["AssignedCI_UniqueID"].StringValue = UniqueID; //String
                newDeployment["AssignedCIs"].IntegerArrayValue = newArrayAssignedCIs; //SInt32 
                newDeployment["AssignmentAction"].IntegerValue = 2; //SInt32 
                newDeployment["AssignmentDescription"].StringValue = newAdvertisementComment; //String
                //newDeployment["AssignmentID"]; //SInt32 
                newDeployment["AssignmentName"].StringValue = existingProgramName + "_" + existingCollectionID + "_" + "_Install"; //String
                newDeployment["AssignmentType"].IntegerValue = 2; //SInt32 CIA_TYPE_APPLICATION
                newDeployment["AssignmentUniqueID"].StringValue = Guid.NewGuid().ToString(); //String
                //newDeployment["CollectionName"].StringValue = existingCollectionID; //String
                newDeployment["ContainsExpiredUpdates"].BooleanValue = false; //Boolean
                newDeployment["CreationTime"].DateTimeValue = newAdvertisementStartOfferDateTime; //DateTime
                newDeployment["DesiredConfigType"].IntegerValue = 1; //SInt32 
                newDeployment["DisableMomAlerts"].BooleanValue = false; //Boolean
                newDeployment["DPLocality"].IntegerValue = 80; //UInt32
                newDeployment["Enabled"].BooleanValue = true; //Boolean
                //newDeployment["EvaluationSchedule"]; //String
                //newDeployment["ExpirationTime"]; //DateTime
                //newDeployment["LastModificationTime"]; //DateTime
                //newDeployment["LastModifiedBy"]; //String
                newDeployment["LocaleID"].IntegerValue = 1033; //UInt32
                newDeployment["LogComplianceToWinEvent"].BooleanValue = false; //Boolean
                //newDeployment["NonComplianceCriticality"]; //SInt32 
                newDeployment["NotifyUser"].BooleanValue = false; //Boolean
                //newDeployment["OfferFlags"].IntegerValue = 0; //UInt32
                newDeployment["OfferTypeID"].IntegerValue = Convert.ToInt32(guiConfig.SelectSingleNode("/AppImporter/deploymentpurpose").InnerText);
                // If the deployment is required also set Enforcement Deadline to now/"As soon as possible"
                switch (guiConfig.SelectSingleNode("/AppImporter/deploymentpurpose").InnerText)
                {
                    case "0":
                        newDeployment["EnforcementDeadline"].DateTimeValue = newAdvertisementStartOfferDateTime; //DateTime
                        break;
                    default:
                        break;
                }
                //newDeployment["OfferTypeID"].IntegerValue = 2; //SInt32 0 = Required, 2 = AVAILABLE , 3 = Simulated
                newDeployment["OverrideServiceWindows"].BooleanValue = false; //Boolean
                newDeployment["PersistOnWriteFilterDevices"].BooleanValue = false; //Boolean
                newDeployment["Priority"].IntegerValue = 1; //SInt32 
                newDeployment["RaiseMomAlertsOnFailure"].BooleanValue = false; //Boolean
                newDeployment["RebootOutsideOfServiceWindows"].BooleanValue = false; //Boolean
                newDeployment["RequireApproval"].BooleanValue = false; //Boolean
                newDeployment["SendDetailedNonComplianceStatus"].BooleanValue = false; //Boolean
                newDeployment["SourceSite"].StringValue = guiConfig.SelectSingleNode("/AppImporter/SCCMSiteCode").InnerText; //String
                newDeployment["StartTime"].DateTimeValue = newAdvertisementStartOfferDateTime.AddMinutes(0); //DateTime
                newDeployment["StateMessagePriority"].IntegerValue = 5; //UInt32
                newDeployment["SuppressReboot"].IntegerValue = 0; //UInt32
                newDeployment["TargetCollectionID"].StringValue = existingCollectionID; //String
                //newDeployment["UpdateDeadline"]; //DateTime
                newDeployment["UpdateSupersedence"].BooleanValue = false; //Boolean
                newDeployment["UseGMTTimes"].BooleanValue = false; //Boolean
                newDeployment["UserUIExperience"].BooleanValue = true; //Boolean
                newDeployment["WoLEnabled"].BooleanValue = false; //Boolean

                // Save the new advertisment and properties.
                newDeployment.Put();
                newDeployment.Get();


            }
            catch (SmsException ex)
            {
                Ballontip("Error", "Failed to create deployment type. Error: " + ex.Message, ToolTipIcon.Error, 6000);
                //Console.WriteLine("Failed to assign advertisement. Error: " + ex.Message);
                throw;
            }
        }

        public void MoveConsoleFolderItem(WqlConnectionManager connection, string itemObjectID, Int32 objectType, Int32 sourceContainerID, Int32 destinationContainerID)
        {
            try
            {
                Dictionary<string, object> parameters = new Dictionary<string, object>();
                string[] sourceItems = new string[1];
                // Only one item is being moved, the array size is 1.

                sourceItems[0] = itemObjectID;
                parameters.Add("InstanceKeys", sourceItems);
                parameters.Add("ContainerNodeID", sourceContainerID);
                parameters.Add("TargetContainerNodeID", destinationContainerID);
                parameters.Add("ObjectType", objectType);
                connection.ExecuteMethod("SMS_ObjectContainerItem", "MoveMembers", parameters);
            }
            catch (SmsException e)
            {
                Console.WriteLine("Failed to move folder item. Error: " + e.Message);
                throw;
            }
        }
        #endregion SCCM Functions

    }
}
